package com.aps.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 染色体类（遗传算法中的解表示）
 * 
 * 在APS排程系统的遗传算法中，染色体代表一个完整的排产方案。
 * 基因序列由工序组成，表示工序的执行顺序。
 * 
 * 遗传算法核心概念：
 * - 染色体：完整的解决方案（排产方案）
 * - 基因：解决方案的组成部分（工序）
 * - 适应度：解决方案质量的数值化评估
 * 
 * 业务场景：
 * - 染色体1：[J1-1, J2-1, J1-2, J3-1, J2-2, J1-3, J3-2, J3-3] 
 * - 染色体2：[J2-1, J1-1, J3-1, J1-2, J3-2, J2-2, J1-3, J3-3]
 * - 每个染色体代表不同的工序执行顺序，会产生不同的排产效果
 * 
 * @author APS System
 * @version 1.0
 */
public class Chromosome {
    
    /** 基因序列，即工序执行顺序 */
    private List<Operation> geneSequence;
    
    /** 适应度值，用于评估该排产方案的优劣程度 */
    private double fitness;
    
    /** 是否存在机器时间冲突 */
    private boolean hasMachineConflicts;

    /** 记录每个工序分配的具体设备 */
    private Map<Operation, Machine> operationMachineMap = new HashMap<>();


    public String getChromosomeCode() {
        return chromosomeCode;
    }

    public void setChromosomeCode(String chromosomeCode) {
        this.chromosomeCode = chromosomeCode;
    }

    //种群编码 （基于基因维度进行编码） 作用判断是否生成了重复的染色体
    private String chromosomeCode;

    /**
     * 构造函数
     * 
     * @param geneSequence 基因序列（工序执行顺序）
     */
    public Chromosome(List<Operation> geneSequence) {
        this.geneSequence = geneSequence != null ? new ArrayList<>(geneSequence) : new ArrayList<>();
        this.fitness = 0.0;
        this.hasMachineConflicts = false;
    }

    /**
     * 染色体基因排列好后 染色体编码
     * @return
     */
    public void preparedChromosomeCode() {
        if(geneSequence != null && !geneSequence.isEmpty()) {
            this.chromosomeCode = geneSequence.stream().map(item -> {
                //订单 id +  工序id  =  基因
                return item.getOrder().getId() + item.getId();
            }).collect(Collectors.joining("&&"));
        }
    }


    
    /**
     * 默认构造函数，创建空的染色体
     */
    public Chromosome() {
        this(new ArrayList<>());
    }
    
    /**
     * 复制染色体
     * 
     * 在遗传算法的交叉和变异操作中，需要创建染色体的副本
     * 以避免修改原始染色体。
     * 
     * @return 当前染色体的深度拷贝
     */
    public Chromosome copy() {
        Chromosome copy = new Chromosome(new ArrayList<>(this.geneSequence));
        copy.fitness = this.fitness;
        copy.hasMachineConflicts = this.hasMachineConflicts;
        copy.operationMachineMap.putAll(this.operationMachineMap);
        return copy;
    }
    
    /**
     * 添加工序到基因序列
     * 
     * @param operation 要添加的工序
     */
    public void addOperation(Operation operation) {
        if (operation == null) {
            throw new IllegalArgumentException("工序不能为空");
        }
        this.geneSequence.add(operation);
    }
    
    /**
     * 在指定位置插入工序
     * 
     * @param index 插入位置
     * @param operation 要插入的工序
     */
    public void insertOperation(int index, Operation operation) {
        if (operation == null) {
            throw new IllegalArgumentException("工序不能为空");
        }
        if (index < 0 || index > geneSequence.size()) {
            throw new IndexOutOfBoundsException("插入位置超出范围");
        }
        this.geneSequence.add(index, operation);
    }
    
    /**
     * 移除指定位置的工序
     * 
     * @param index 要移除的位置
     * @return 被移除的工序
     */
    public Operation removeOperation(int index) {
        if (index < 0 || index >= geneSequence.size()) {
            throw new IndexOutOfBoundsException("移除位置超出范围");
        }
        return this.geneSequence.remove(index);
    }
    
    /**
     * 交换两个位置的工序
     * 
     * 用于变异操作中的基因交换
     * 
     * @param index1 第一个位置
     * @param index2 第二个位置
     */
    public void swapOperations(int index1, int index2) {
        if (index1 < 0 || index1 >= geneSequence.size() || 
            index2 < 0 || index2 >= geneSequence.size()) {
            throw new IndexOutOfBoundsException("交换位置超出范围");
        }
        
        if (index1 != index2) {
            Operation temp = geneSequence.get(index1);
            geneSequence.set(index1, geneSequence.get(index2));
            geneSequence.set(index2, temp);
        }
    }
    
    /**
     * 获取基因序列的长度
     * 
     * @return 基因序列长度
     */
    public int getGeneLength() {
        return geneSequence.size();
    }
    
    /**
     * 检查染色体是否为空
     * 
     * @return 如果基因序列为空返回true，否则返回false
     */
    public boolean isEmpty() {
        return geneSequence.isEmpty();
    }
    
    /**
     * 验证染色体的有效性
     * 
     * 检查基因序列是否符合APS排程的约束条件：
     * 1. 每个订单的工序必须按正确顺序排列
     * 2. 不能有重复的工序
     * 3. 不能有缺失的工序
     * 
     * @param expectedOperations 期望的工序列表（用于验证完整性）
     * @return 如果染色体有效返回true，否则返回false
     */
    public boolean isValid(List<Operation> expectedOperations) {
        if (geneSequence.size() != expectedOperations.size()) {
            return false;
        }
        
        // 检查是否包含所有期望的工序
        List<String> expectedIds = expectedOperations.stream()
                .map(Operation::getId)
                .sorted()
                .collect(Collectors.toList());
        
        List<String> actualIds = geneSequence.stream()
                .map(Operation::getId)
                .sorted()
                .collect(Collectors.toList());
        
        if (!expectedIds.equals(actualIds)) {
            return false;
        }
        
        // 检查每个订单的工序顺序是否正确
        return isOrderSequenceValid();
    }
    
    /**
     * 检查订单工序顺序是否有效
     * 
     * @return 如果所有订单的工序都按正确顺序排列返回true，否则返回false
     */
    private boolean isOrderSequenceValid() {
        // 按订单分组
        var orderGroups = geneSequence.stream()
                .collect(Collectors.groupingBy(op -> op.getOrder().getId()));
        
        // 检查每个订单的工序顺序
        for (List<Operation> orderOps : orderGroups.values()) {
            orderOps.sort((o1, o2) -> {
                // 按在基因序列中的出现顺序排序
                return Integer.compare(geneSequence.indexOf(o1), geneSequence.indexOf(o2));
            });
            
            // 检查工序顺序号是否递增
            for (int i = 1; i < orderOps.size(); i++) {
                if (orderOps.get(i).getSequence() <= orderOps.get(i-1).getSequence()) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
//    /**
//     * 获取染色体的统计信息
//     *
//     * @return 包含统计信息的字符串
//     */
//    public String getStatistics() {
//        if (geneSequence.isEmpty()) {
//            return "空染色体";
//        }
//
//        long orderCount = geneSequence.stream()
//                .map(op -> op.getOrder().getId())
//                .distinct()
//                .count();
//
//        long machineCount = geneSequence.stream()
//                .map(op -> op.getMachine().getId())
//                .distinct()
//                .count();
//
//        return String.format("工序数:%d, 订单数:%d, 设备数:%d, 适应度:%.4f, 冲突:%s",
//                geneSequence.size(),
//                orderCount,
//                machineCount,
//                fitness,
//                hasMachineConflicts ? "是" : "否");
//    }
    
    // Getter和Setter方法
    
    /**
     * 获取基因序列
     * 
     * @return 基因序列
     */
    public List<Operation> getGeneSequence() {
        return geneSequence;
    }
    
    /**
     * 设置基因序列
     * 
     * @param geneSequence 基因序列
     */
    public void setGeneSequence(List<Operation> geneSequence) {
        this.geneSequence = geneSequence != null ? geneSequence : new ArrayList<>();
    }
    
    /**
     * 获取适应度值
     * 
     * @return 适应度值
     */
    public double getFitness() {
        return fitness;
    }
    
    /**
     * 设置适应度值
     * 
     * @param fitness 适应度值
     */
    public void setFitness(double fitness) {
        this.fitness = fitness;
    }
    
    /**
     * 检查是否存在机器冲突
     * 
     * @return 是否存在机器冲突
     */
    public boolean hasMachineConflicts() {
        return hasMachineConflicts;
    }
    
    /**
     * 设置是否存在机器冲突
     * 
     * @param hasMachineConflicts 是否存在机器冲突
     */
    public void setHasMachineConflicts(boolean hasMachineConflicts) {
        this.hasMachineConflicts = hasMachineConflicts;
    }
    
    /**
     * 获取工序到设备的映射
     * 
     * @return 工序到设备的映射
     */
    public Map<Operation, Machine> getOperationMachineMap() { return operationMachineMap; }
    /**
     * toString方法，便于调试和日志输出
     * 
     * @return 格式化的字符串表示
     */
    @Override
    public String toString() {
        String sequenceStr = geneSequence.stream()
                .map(Operation::getId)
                .collect(Collectors.joining(" -> "));
        
        return String.format("染色体[适应度:%.4f, 冲突:%s]: %s", 
                fitness,
                hasMachineConflicts ? "是" : "否",
                sequenceStr.isEmpty() ? "空" : sequenceStr);
    }
    
    /**
     * equals方法，基于基因序列进行比较
     * 
     * @param obj 要比较的对象
     * @return 如果基因序列相同返回true，否则返回false
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Chromosome that = (Chromosome) obj;
        return geneSequence.equals(that.geneSequence);
    }
    
    /**
     * hashCode方法，基于基因序列
     * 
     * @return 散列值
     */
    @Override
    public int hashCode() {
        return geneSequence.hashCode();
    }
}
